﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using mySnake.GamePage;
using static mySnake.GameParam;

namespace mySnake
{
    public partial class MainForm : Form
    {
        private readonly GameParam gameParam;
        private event EventHandler GameStatusChangeEvent;
        private DescForm descForm;
        private FailForm failForm;
        public MainForm()
        {
            AutoScaleMode = AutoScaleMode.Dpi;
            InitializeComponent();
            this.KeyPreview = true;

            // 游戏参数初始化
            gameParam = new GameParam.Builder()
                .setRows(21)
                .setCols(38)
                .setBlockWidth(20)
                .build();
            gameParam.InitSnake();
            gameParam.ScoreEvent += EatScoreHandle;
            gameParam.GameStatusChangeEvent += GameStatusChangeHandle;

            GameStatusChangeEvent += GameStatusChangeHandle;

            // 游戏说明窗口
            descForm = new DescForm();
            failForm = new FailForm();

        }

        // 控件绘制事件
        private void PanelMainPaint(object sender, PaintEventArgs e)
        {
            ControlPaint.DrawBorder(e.Graphics, panelMain.ClientRectangle, Color.LightGray, ButtonBorderStyle.Solid);
            PrintMap(e.Graphics);
            PrintSnake(e.Graphics, gameParam.snake);
            PrintScoreNode(e.Graphics, gameParam.scoreNode);
        }

        #region 防止闪屏
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;
                return cp;
            }
        }
        #endregion

        // 画方块地图
        private void PrintMap(Graphics g)
        {
            for (int i = 1; i <= gameParam.Rows; i++)
            {
                for (int j = 1; j <= gameParam.Cols; j++)
                {
                    int x = j * gameParam.BlockWidth + (j - 1) * 4;
                    int y = i * gameParam.BlockWidth + (i - 1) * 4;
                    PrintBlock(g, Color.LightGray, x, y, gameParam.BlockWidth);
                }
            }
        }

        // 画单一方块
        private void PrintBlock(Graphics g, Color color, int x, int y, int blockWidth)
        {
            SolidBrush brush = new SolidBrush(color);
            Rectangle rect = new Rectangle(x, y, blockWidth, blockWidth);
            g.FillRectangle(brush, rect);
        }

        // 画snake身体
        public void PrintSnake(Graphics g, List<SnakeNode> snake)
        {
            foreach (var snakeNode in snake)
            {
                PrintBlock(g, snakeNode.Color, snakeNode.X, snakeNode.Y, snakeNode.BlockWidth);
            }
        }

        // 画得分节点
        public void PrintScoreNode(Graphics g, SnakeNode scoreNode)
        {
            PrintBlock(g, scoreNode.Color, scoreNode.X, scoreNode.Y, scoreNode.BlockWidth);
        }

        // 定时器超时事件处理
        private void TimerGameTick(object sender, EventArgs e)
        {
            Debug.WriteLine("game ticker");
            gameParam.SpeedCounter++;

            if (gameParam.SpeedCounter >= ((int)gameParam.GameSpeed))
            {
                if (gameParam.GameStatus == GAME_STATUS.GAME_STATUS_RUNNING)
                {
                    gameParam.GenMoveSnake();
                    panelMain.Refresh();
                }
                gameParam.SpeedCounter = 0;
            }

        }

        // 重置游戏
        private void ResetGame()
        {
            gameParam.InitSnake();
            panelMain.Refresh();

            buttonStartGame.Text = "开始游戏";
            labelScore.Text = "得分：0";
        }

        // 普通按键监听
        protected override bool ProcessDialogKey(Keys keyData)
        {
            Debug.WriteLine($"key press: {keyData}");
            switch (keyData)
            {
                case Keys.Up:
                    gameParam.KeyDirection = GAME_DIRECTION.GAME_DIRECTION_UP;
                    return false;
                case Keys.Down:
                    gameParam.KeyDirection = GAME_DIRECTION.GAME_DIRECTION_DOWN;
                    return false;
                case Keys.Right:
                    gameParam.KeyDirection = GAME_DIRECTION.GAME_DIRECTION_RIGHT;
                    return false;
                case Keys.Left:
                    gameParam.KeyDirection = GAME_DIRECTION.GAME_DIRECTION_LEFT;
                    return false;
                default:
                    return base.ProcessDialogKey(keyData);
            }
        }

        // 功能按键监听
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            // 屏蔽空格键触发按钮
            if (keyData == Keys.Space)
            {
                GameStatusEventArgs gameStatusEventArgs = new GameStatusEventArgs();
                if (gameParam.GameStatus == GAME_STATUS.GAME_STATUS_PAUSED)
                {
                    gameStatusEventArgs.GameStatus = GAME_STATUS.GAME_STATUS_RUNNING;
                }
                else
                {
                    gameStatusEventArgs.GameStatus = GAME_STATUS.GAME_STATUS_PAUSED;
                }
                GameStatusChangeEvent.Invoke(this, gameStatusEventArgs);

                return true;
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }

        // 开始游戏按钮
        private void StartGameBtnClicked(object sender, EventArgs e)
        {
            Debug.WriteLine("start game");
            GameStatusEventArgs gameStatusEventArgs = new GameStatusEventArgs();
            if (gameParam.GameStatus == GAME_STATUS.GAME_STATUS_PAUSED)
            {
                gameStatusEventArgs.GameStatus = GAME_STATUS.GAME_STATUS_RUNNING;
            }
            else
            {
                gameStatusEventArgs.GameStatus = GAME_STATUS.GAME_STATUS_PAUSED;
            }
            GameStatusChangeEvent.Invoke(this, gameStatusEventArgs);
        }

        // 处理得分事件
        private void EatScoreHandle(object sender, EventArgs args)
        {
            Debug.WriteLine("eat score");
            int score = (args as ScoreEventArgs).Score;
            labelScore.Text = "得分：" + score;

            if (score > 0 && score < 3)
            {
                gameParam.GameSpeed = GAME_SPEED.GAME_SPEED_LOWER;
            }
            else if (score >= 3 && score < 6)
            {
                gameParam.GameSpeed = GAME_SPEED.GAME_SPEED_NORMAL;
            }
            else if (score >= 6 && score < 10)
            {
                gameParam.GameSpeed = GAME_SPEED.GAME_SPEED_MEDIUM;
            }
            else if (score >= 10)
            {
                gameParam.GameSpeed = GAME_SPEED.GAME_SPEED_HARD;
            }
        }

        // 处理游戏状态改变事件
        private void GameStatusChangeHandle(object sender, EventArgs args)
        {
            Debug.WriteLine("game status change");
            GAME_STATUS status = (args as GameStatusEventArgs).GameStatus;
            gameParam.GameStatus = status;

            switch (status)
            {
                case GAME_STATUS.GAME_STATUS_RUNNING:
                    {
                        buttonStartGame.Text = "暂停游戏";
                    }
                    break;
                case GAME_STATUS.GAME_STATUS_PAUSED:
                    {
                        buttonStartGame.Text = "开始游戏";
                    }
                    break;
                case GAME_STATUS.GAME_STATUS_FINISH:
                    {
                        failForm.ShowDialog();
                        ResetGame();
                    }
                    break;
            }
        }

        // 游戏说明按钮
        private void ButtonDescClick(object sender, EventArgs e)
        {
            descForm.ShowDialog();
        }

        // 退出游戏按钮
        private void BtnQuitClicked(object sender, EventArgs e)
        {
            Application.Exit();
        }
    }
}
